package com.nonagon.melladesk.handler;

import com.nonagon.melladesk.annotation.Login;
import com.nonagon.melladesk.utils.GraphQLUtil;
import com.nonagon.melladesk.utils.R;
import com.nonagon.melladesk.utils.StatusCode;
import lombok.RequiredArgsConstructor;
import org.mountcloud.graphql.GraphqlClient;
import org.mountcloud.graphql.request.mutation.GraphqlMutation;
import org.mountcloud.graphql.request.query.GraphqlQuery;
import org.mountcloud.graphql.request.result.ResultAttributtes;
import org.mountcloud.graphql.response.GraphqlResponse;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import static org.springframework.web.reactive.function.server.ServerResponse.notFound;

/**
 * @author flitsneak
 * @ClassName
 * @date 2021/4/12 9:46
 */
@Component
@RequiredArgsConstructor
public class VetSpireHandler {

    static final String serverUrl = "https://api2.vetspire.com/graphql";

    //假设这是个池子
    public static GraphQLUtil graphQLUtil(){
        GraphQLUtil graphQLUtil = new GraphQLUtil();
        return graphQLUtil;
    }

    public static GraphqlClient graphqlClient(){
        return GraphqlClient.buildGraphqlClient(serverUrl);
    }

    /**
     * 查找所organization信息
     * @param serverRequest
     * @return
     */
    @Login
    public Mono<ServerResponse> selectLocationsByOrganization(ServerRequest serverRequest){

        GraphQLUtil graphQLUtil = graphQLUtil();
        GraphqlClient graphqlClient = graphqlClient();

        String queryName = "org";
        return serverRequest.bodyToMono(Map.class)
                .flatMap(p->{
                    GraphqlQuery query = graphQLUtil.buildGraphQL(graphqlClient, queryName,p.get("APIkey").toString());
                    query.addResultAttributes("id", "name");
                    GraphqlResponse response = null;
                    try {
                        response = graphqlClient.doQuery(query);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue(new R(true, StatusCode.SUCCESS.getCode(), StatusCode.SUCCESS.getMsg(),response.getData().get("data")));
                }).switchIfEmpty(notFound().build());
    }

    /**
     * 查找所有locations以及providers
     * @param serverRequest
     * @return
     */
    public Mono<ServerResponse> selectLocations(ServerRequest serverRequest){
        GraphQLUtil graphQLUtil = graphQLUtil();
        GraphqlClient graphqlClient = graphqlClient();

        String queryName = "Locations";
        return serverRequest.bodyToMono(Map.class)
                .flatMap(p->{
                    GraphqlQuery query = graphQLUtil.buildGraphQL(graphqlClient, queryName,p.get("APIkey").toString());
                    query.addResultAttributes("id", "name","displayName","address email","phoneNumber","url");
                    ResultAttributtes providerAttr = new ResultAttributtes("providers");
                    providerAttr.addResultAttributes("id","username","email","name");
                    query.addResultAttributes(providerAttr);

                    GraphqlResponse response = null;
                    try {
                        response = graphqlClient.doQuery(query);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue(new R(true, StatusCode.SUCCESS.getCode(), StatusCode.SUCCESS.getMsg(),response.getData().get("data")));
                }).switchIfEmpty(notFound().build());

    }

    /**
     * 根据locationid查找所有工作人员
     * @param serverRequest
     * @return
     */
    public Mono<ServerResponse> selectProvidersByLocationId(ServerRequest serverRequest){
        GraphQLUtil graphQLUtil = graphQLUtil();
        GraphqlClient graphqlClient = graphqlClient();

        String queryName = "Locations";

        return serverRequest.bodyToMono(Map.class)
                .flatMap(p->{
                    GraphqlQuery query = graphQLUtil.buildGraphQL(graphqlClient, queryName,p.get("APIkey").toString());

                    query.addParameter("id",p.get("locationId").toString());
                    ResultAttributtes providersAttr = new ResultAttributtes("providers");
                    providersAttr.addResultAttributes("id","username","email","name");

                    query.addResultAttributes(providersAttr);

                    GraphqlResponse response = null;
                    try {
                        response = graphqlClient.doQuery(query);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue(new R(true, StatusCode.SUCCESS.getCode(), StatusCode.SUCCESS.getMsg(),response.getData().get("data")));
                }).switchIfEmpty(notFound().build());
    }

    /**
     * 查找所有宠物信息
     * @param serverRequest
     * @return
     */
    public Mono<ServerResponse> selectAllPets(ServerRequest serverRequest){

        GraphQLUtil graphQLUtil = graphQLUtil();
        GraphqlClient graphqlClient = graphqlClient();

        String queryName = "patients";
        return serverRequest.bodyToMono(Map.class)
                .flatMap(p->{
                    GraphqlQuery query = graphQLUtil.buildGraphQL(graphqlClient, queryName,p.get("APIkey").toString());

                    //设置需要查询的参数是id和name
                    query.addResultAttributes("id", "name","breed","sex","birthDay","birthMonth","birthYear");

                    ResultAttributtes weightAttr = new ResultAttributtes("latestWeight");
                    weightAttr.addResultAttributes("unit","value");

                    ResultAttributtes clientAttr = new ResultAttributtes("client");
                    clientAttr.addResultAttributes("name");

                    query.addResultAttributes(weightAttr);

                    query.addResultAttributes(clientAttr);

                    GraphqlResponse response = null;
                    try {
                        response = graphqlClient.doQuery(query);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue(new R(true, StatusCode.SUCCESS.getCode(), StatusCode.SUCCESS.getMsg(),response.getData().get("data")));
                }).switchIfEmpty(notFound().build());
    }

    /**
     * 根据宠物id获取病例信息
     * @param serverRequest
     * @return
     */
    public Mono<ServerResponse> selectExamByPatientId(ServerRequest serverRequest){

        GraphQLUtil graphQLUtil = graphQLUtil();
        GraphqlClient graphqlClient = graphqlClient();

        String queryName = "encounters";
        return serverRequest.bodyToMono(Map.class)
                .flatMap(p->{
                    GraphqlQuery query = graphQLUtil.buildGraphQL(graphqlClient, queryName,p.get("APIkey").toString());

                    query.addParameter("patientId",p.get("patientId").toString()).addParameter("updatedAtStart","2020-01-01T00:00:00Z").addParameter("limit",5);

                    //设置需要查询的参数是id和name
                    query.addResultAttributes("id", "title","insertedAt","updatedAt");

                    ResultAttributtes patientAttr = new ResultAttributtes("patient");
                    patientAttr.addResultAttributes("id","name");

                    ResultAttributtes vitalsAttr = new ResultAttributtes("vitals");
                    vitalsAttr.addResultAttributes("id","temp","insertedAt","updatedAt");

                    ResultAttributtes customsAttr = new ResultAttributtes("customs");
                    customsAttr.addResultAttributes("id","name","value");

                    vitalsAttr.addResultAttributes(customsAttr);

                    query.addResultAttributes(patientAttr);

                    query.addResultAttributes(vitalsAttr);

                    GraphqlResponse response = null;
                    try {
                        response = graphqlClient.doQuery(query);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue(new R(true, StatusCode.SUCCESS.getCode(), StatusCode.SUCCESS.getMsg(),response.getData().get("data")));
                }).switchIfEmpty(notFound().build());
    }

    /**
     * 更新note信息
     * @param serverRequest
     * @return
     */
    public Mono<ServerResponse> updateNoteByVitalId(ServerRequest serverRequest){

        GraphQLUtil graphQLUtil = graphQLUtil();
        GraphqlClient graphqlClient = graphqlClient();

        String queryName = "updateVitals";
        return serverRequest.bodyToMono(Map.class)
                .flatMap(p->{
                    GraphqlMutation mutation = graphQLUtil.buildMutation(graphqlClient, queryName,p.get("APIkey").toString());

                    Map input = new HashMap();
                    Map customs = new HashMap();
                    customs.put("name",p.get("customsName").toString());
                    customs.put("value",p.get("customsValue").toString());
                    input.put("customs",customs);
                    mutation.addParameter("id",p.get("vitalId").toString()).addObjectParameter("input",input);

                    mutation.addResultAttributes("id","temp");

                    ResultAttributtes customsAttr = new ResultAttributtes("customs").addResultAttributes("id","name","value");

                    mutation.addResultAttributes(customsAttr);

                    GraphqlResponse response = null;
                    try {
                        response = graphqlClient.doMutation(mutation);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue(new R(true, StatusCode.SUCCESS.getCode(), StatusCode.SUCCESS.getMsg(),response.getData().get("data")));
                }).switchIfEmpty(notFound().build());
    }

    /**
     * 根据providerId查找encounters
     * @param serverRequest
     * @return
     */
    public Mono<ServerResponse> selectPatientsByProviderId(ServerRequest serverRequest){

        GraphQLUtil graphQLUtil = graphQLUtil();
        GraphqlClient graphqlClient = graphqlClient();

        String queryName = "encounters";
        return serverRequest.bodyToMono(Map.class)
                .flatMap(p->{
                    GraphqlQuery query = graphQLUtil.buildGraphQL(graphqlClient, queryName,p.get("APIkey").toString());

                    query.addParameter("providerId",p.get("providerId").toString()).addParameter("updatedAtStart",p.get("updateAtStart").toString()+"T00:00:00Z").addParameter("limit",5);

                    ResultAttributtes patientAttr = new ResultAttributtes("patient");
                    patientAttr.addResultAttributes("id","name","birthDate","birthMonth","birthYear","color","sex","species","clientId","updatedAt","insertedAt","breed");

                    ResultAttributtes locationAttr = new ResultAttributtes("location");
                    locationAttr.addResultAttributes("id","name");

                    ResultAttributtes vitalsAttr = new ResultAttributtes("latestWeight");
                    vitalsAttr.addResultAttributes("unit","value");
                    ResultAttributtes clientAttr = new ResultAttributtes("client");
                    clientAttr.addResultAttributes("name");
                    patientAttr.addResultAttributes(vitalsAttr,clientAttr);

                    query.addResultAttributes(locationAttr,patientAttr);

                    GraphqlResponse response = null;
                    try {
                        response = graphqlClient.doQuery(query);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue(new R(true, StatusCode.SUCCESS.getCode(), StatusCode.SUCCESS.getMsg(),response.getData().get("data")));
                }).switchIfEmpty(notFound().build());
    }

    /**
     * 根据providerId查找最新的encounter
     * @param serverRequest
     * @return
     */
    public Mono<ServerResponse> selectLatestExamsByPatientId(ServerRequest serverRequest){

        GraphQLUtil graphQLUtil = graphQLUtil();
        GraphqlClient graphqlClient = graphqlClient();

        String queryName = "encounters";
        return serverRequest.bodyToMono(Map.class)
                .flatMap(p->{
                    GraphqlQuery query = graphQLUtil.buildGraphQL(graphqlClient, queryName,p.get("APIkey").toString());

                    query.addParameter("patientId",p.get("patientId").toString()).addParameter("updatedAtStart",p.get("updateAtStart").toString()+"T00:00:00Z").addParameter("limit",5);

                    //设置需要查询的参数是id和name
                    query.addResultAttributes("id", "title","insertedAt","updatedAt");

                    ResultAttributtes patientAttr = new ResultAttributtes("patient");
                    patientAttr.addResultAttributes("id","name");

                    ResultAttributtes vitalsAttr = new ResultAttributtes("vitals");
                    vitalsAttr.addResultAttributes("id","temp","insertedAt","updatedAt");

                    ResultAttributtes customsAttr = new ResultAttributtes("customs");
                    customsAttr.addResultAttributes("id","name","value");

                    vitalsAttr.addResultAttributes(customsAttr);

                    query.addResultAttributes(patientAttr);

                    query.addResultAttributes(vitalsAttr);

                    GraphqlResponse response = null;
                    try {
                        response = graphqlClient.doQuery(query);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue(new R(true, StatusCode.SUCCESS.getCode(), StatusCode.SUCCESS.getMsg(),response.getData().get("data")));
                }).switchIfEmpty(notFound().build());
    }

    /**
     * 根据providerId查找历史encounters
     * @param serverRequest
     * @return
     */
    public Mono<ServerResponse> selectHistoryExamsByPatientId(ServerRequest serverRequest){

        GraphQLUtil graphQLUtil = graphQLUtil();
        GraphqlClient graphqlClient = graphqlClient();

        String queryName = "encounters";
        return serverRequest.bodyToMono(Map.class)
                .flatMap(p->{
                    GraphqlQuery query = graphQLUtil.buildGraphQL(graphqlClient, queryName,p.get("APIkey").toString());

                    query.addParameter("patientId",p.get("patientId").toString()).addParameter("updatedAtEnd",p.get("updateAtEnd").toString()+"T00:00:00Z").addParameter("limit",5);

                    //设置需要查询的参数是id和name
                    query.addResultAttributes("id", "title","insertedAt","updatedAt");

                    ResultAttributtes patientAttr = new ResultAttributtes("patient");
                    patientAttr.addResultAttributes("id","name");

                    ResultAttributtes vitalsAttr = new ResultAttributtes("vitals");
                    vitalsAttr.addResultAttributes("id","temp","insertedAt","updatedAt");

                    ResultAttributtes customsAttr = new ResultAttributtes("customs");
                    customsAttr.addResultAttributes("id","name","value");

                    vitalsAttr.addResultAttributes(customsAttr);

                    query.addResultAttributes(patientAttr);

                    query.addResultAttributes(vitalsAttr);

                    GraphqlResponse response = null;
                    try {
                        response = graphqlClient.doQuery(query);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue(new R(true, StatusCode.SUCCESS.getCode(), StatusCode.SUCCESS.getMsg(),response.getData().get("data")));
                }).switchIfEmpty(notFound().build());
    }

    /**
     * 根据VitalId更新体温数值
     * @param serverRequest
     * @return
     */
    public Mono<ServerResponse> updateVitalsTemperatureByVitalId(ServerRequest serverRequest){

        GraphQLUtil graphQLUtil = graphQLUtil();
        GraphqlClient graphqlClient = graphqlClient();

        String queryName = "updateVitals";
        return serverRequest.bodyToMono(Map.class)
                .flatMap(p->{
                    GraphqlMutation mutation = graphQLUtil.buildMutation(graphqlClient, queryName,p.get("APIkey").toString());

                    Map input = new HashMap();
                    input.put("temp",p.get("temp").toString());
                    mutation.addParameter("id",p.get("vitalId").toString()).addObjectParameter("input",input);

                    mutation.addResultAttributes("id","heartRate","temp","weight");

                    GraphqlResponse response = null;
                    try {
                        response = graphqlClient.doMutation(mutation);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue(new R(true, StatusCode.SUCCESS.getCode(), StatusCode.SUCCESS.getMsg(),response.getData().get("data")));
                }).switchIfEmpty(notFound().build());
    }

}
